package com.palmwindActivity.proto;

import java.io.ByteArrayOutputStream;
import java.util.Vector;



public class ProtoBufUtil {
	public static ProtoBuf[] toBufArray(byte[] data)
	{
		if(data == null || data.length == 0)
		{
			return null;
		}
		Vector bufferList = new Vector();
		int offset = 0;
		while(data.length > offset)
		{
			ProtoBuf buffer = new ProtoBuf();
			//int objTypeLen = DataUtil.readInt(data, offset);//TODO : readShort is enough?
			int objTypeLen = readInt(data, offset);//TODO : readShort is enough?
			offset += 4;
			String objType = new String(data, offset, objTypeLen);
			buffer.setObjType(objType);
			offset += objTypeLen;

			//int binDataLen = DataUtil.readInt(data, offset);
			int binDataLen = readInt(data, offset);
			if(binDataLen >= 0)
			{
				offset += 4;
				byte[] binData = new byte[binDataLen];
				for(int i = 0; i < binDataLen; i++)
				{
					binData[i] = data[offset++];
				}
				buffer.setBufferData(binData);
				//offset += binDataLen;
			}
			bufferList.addElement(buffer);
		}
		if(bufferList.size() > 0)
		{
			//Can not use this API in RIM
			//return (ProtocolBuffer[])bufferList.toArray(new ProtocolBuffer[0]);
			ProtoBuf[] protoBufferArray = new ProtoBuf[bufferList.size()];
			for(int i = 0; i < protoBufferArray.length; i++)
			{
				protoBufferArray[i] = (ProtoBuf)bufferList.elementAt(i);
			}
			return protoBufferArray;
		}
		else
		{
			return null;
		}
	}
	
	public static byte[] listToByteArray(Vector list)
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try
		{
			for(int i = 0; i < list.size(); i++)
			{
				ProtoBuf buffer = (ProtoBuf)list.elementAt(i);
				byte[] objTypeBin = buffer.getObjType().getBytes();
				byte[] objTypeLen = new byte[4];
				//DataUtil.writeInt(objTypeLen, objTypeBin.length, 0);
				writeInt(objTypeLen, objTypeBin.length, 0);
				baos.write(objTypeLen);
				if(objTypeBin != null)
				{
					baos.write(objTypeBin);
				}
				
				byte[] contentBin = buffer.getBufferData();
				byte[] contentBinLen = new byte[4];
				//DataUtil.write(contentBinLen, contentBin.length, 0);
				write(contentBinLen, contentBin.length, 0);
				baos.write(contentBinLen);
				if(contentBin != null)
				{
					baos.write(contentBin);
				}
			}
		}
		catch(Exception ex)
		{		
		}
		return baos.toByteArray();
	}
	
	static public int readInt(byte[] buff, int offset)
	{
		int mask = 0xFF;
		return (mask & buff[offset]) + ((mask & buff[offset+1]) << 8) + ((mask & buff[offset+2]) << 16) + ((int) buff[offset+3] << 24);
	}
	
	public static int write(byte[] buff, int value, int offset)
	{
		if (value >= -128 && value <= 127)
		{
			buff[offset] = (byte)value;
			return 1;
		}
		else if (value >= -32768 && value <= 32767)
		{
			writeShort(buff, value, offset);
			return 2;
		}
		else if (value >= -8388608 && value <= 8388607)
		{
			buff[offset] = (byte) (value & 0xFF);
			value = value >> 8;
			buff[offset+1] = (byte) (value & 0xFF);
			value = value >> 8;
			buff[offset+2] = (byte) (value & 0xFF);
			return 3;
		}
		else
		{
			writeInt(buff, value, offset);
			return 4;
		}
	}
	
	/**
	 * write an int as SHORT into the byte array: only write 2 bytes.
	 * @param buff
	 * @param num
	 * @param offset
	 */
	static public void writeShort(byte [] buff, int num, int offset)
	{
		buff[offset] = (byte) (num & 0xFF);
		num = num >> 8;
		buff[offset+1] = (byte) (num & 0xFF);
	}
	
	/**
	 * write an int into a byte array
	 *
	 * @param num - the number to write
	 * @param offset - the offset into the array to write it to
	 */
	static public void writeInt(byte [] buff, int num, int offset)
	{
		buff[offset] = (byte) (num & 0xFF);
		num = num >> 8;
		buff[offset+1] = (byte) (num & 0xFF);
		num = num >> 8;
		buff[offset+2] = (byte) (num & 0xFF);
		num = num >> 8;
		buff[offset+3] = (byte) (num & 0xFF);
	}

}
